package com.tca.common.learning.webflux.reactor.start;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Random;

/**
 * 异常处理
 * 在响应式流中, 错误(error)是终止信号。当有错误发生时, 它会导致流序列停止, 并且错误信号会沿着操作链条向下传递,
 * 直至遇到subscribe中的错误处理方法。这样的错误还是应该在应用层面解决的。否则, 你可能会将错误信息显示在用户界面,
 * 或者通过某个REST endpoint发出。所以还是建议在subscribe时通过错误处理方法妥善解决错误
 */
public class ExceptionTest {

    public static void main(String[] args) {

        // 使用subscribe()输出
//        testSysOut();

        // 遇到异常返回一个缺省值
//        testOnErrorReturn();

        // 遇到异常捕获并执行一个异常处理方法或计算一个候补值来顶替, 并终止程序
//        testOnErrorConsume();

        // 遇到异常抛出, 并终止程序
        testThrowsException();
    }



    /**
     * 遇到异常输出, 并终止程序
     */
    private static void testSysOut() {
        Flux.range(1, 6)
                .map(i -> 10/(i-3)) // 1
                .map(i -> i*i)
                .subscribe(System.out::println, System.err::println);
    }

    /**
     * 遇到异常捕获并返回一个缺省的值, 并终止程序
     */
    private static void testOnErrorReturn() {
        Flux.range(1, 6)
                .map(i -> 10/(i-3))
                .onErrorReturn(0)   // 1
                .map(i -> i*i)
                .subscribe(System.out::println, System.err::println);
    }

    /**
     * 遇到异常捕获并执行一个异常处理方法或计算一个候补值来顶替, 并终止程序
     */
    private static void testOnErrorConsume() {
        Flux.range(1, 6)
                .map(i -> 10/(i-3))
                .onErrorResume(e -> Mono.just(new Random().nextInt(6))) // 提供新的数据流
                .map(i -> i*i)
                .subscribe(System.out::println, System.err::println);
    }

    /**
     * 遇到异常抛出, 并终止程序
     */
    private static void testThrowsException() {
        Flux.just("timeout1")
                .map(k -> k.substring(-1))   // 1
                .onErrorMap(original -> new Exception("business Exception", original)); // 2

    }
}

